package com.utc.cards.table.jade.agent.rulesAgent;

import jade.core.AID;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.utc.cards.common.jade.Mapper;
import com.utc.cards.model.deck.Deck;
import com.utc.cards.model.game.Info;
import com.utc.cards.model.player.Hands;
import com.utc.cards.model.player.IPlayer;

public class RulesListenerBehaviour extends CyclicBehaviour
{

    private static final long serialVersionUID = -6123951553740920471L;
    private static Logger log = LoggerFactory.getLogger(RulesListenerBehaviour.class);

    private RulesAgent agent;
    private MessageTemplate template = MessageTemplate.MatchConversationId("info");

    public RulesListenerBehaviour(RulesAgent rulesAgent)
    {
        super(rulesAgent);
        this.agent = rulesAgent;
    }

    @Override
    public void action()
    {
        ACLMessage msg = agent.receive(template);
        if (msg != null)
        {
            if (msg.getPerformative() == ACLMessage.INFORM)
            {
                log.debug("RulesListener: New Message: " + msg.getContent());
                Info info = null;
                try
                {
                    info = Mapper.getObjectMapper().readValue(msg.getContent(), Info.class);
                }
                catch (Exception ex)
                {
                    log.error("Error while mapping String to Info");
                    ex.printStackTrace();
                }
                switch (info.getType())
                {
                case PLAYER_START:
                    log.debug("Received PLAYER_START : agent.deteminateFirstPlayer()");
                    agent.deteminateFirstPlayer();
                    break;
                case CARDS_DISTRIBUTION:
                    log.debug("Received CARDS_DISTRIBUTION : agent.distributeInitialCards()");
                    agent.distributeInitialCards();
                    break;
                case VALIDATE_CARDS:
                    log.debug("Received VALIDATE_CARDS : agent.validatePlayerCards()");
                    try
                    {
                        Map<String, AID> playerMap = agent.getModel().getPlayersMap();

                        for (String player : playerMap.keySet())
                        {

                            if (playerMap.get(player).getLocalName().equals(msg.getSender().getLocalName()))
                            {
                                log.debug("Received VALIDATE_CARDS : player match");
                                IPlayer sender = agent.getModel().getGame().getPlayerByName(player);

                                log.debug("extractHands" + info.getJson());
                                Hands hands = Mapper.getObjectMapper().readValue(info.getJson(), Hands.class);
                                log.debug("Received VALIDATE_CARDS deck : " + hands.get(IPlayer.MAIN_HAND));
                                agent.validatePlayerCards(hands.get(IPlayer.MAIN_HAND), sender);
                                break;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        log.error("Error while mapping String to Hands");
                        e.printStackTrace();
                    }
                    break;

                case ASK_ADVICE:
                    log.debug("Received ASK_ADVICE : agent.askAdvice()");
                    Map<String, AID> playerMap = agent.getModel().getPlayersMap();
                    log.debug("sender : " + msg.getSender().getLocalName());
                    for (String playerName : playerMap.keySet())
                    {
                        if (playerMap.get(playerName).getLocalName().equals(msg.getSender().getLocalName()))
                        {
                            log.debug("Computing advice for : " + msg.getSender().getLocalName());
                            IPlayer player = agent.getModel().getGame().getPlayerByName(playerName);
                            Deck deck = player.getHand();
                            agent.askAdvice(deck, player);
                            break;
                        }
                    }
                    break;
                case ESTABLISH_FOLD_WINNER:
                    log.debug("Received ESTABLISH_FOLD_WINNER : agent.determinateWinnerCurrentFold()");
                    agent.determinateWinnerCurrentFold();
                    break;
                // appelé à la fin du jeu
                // a la réception d'un message SCORE, on envoi à tous les joueurs le résultat une fois calculé
                case SCORE:
                    log.debug("Received SCORE : agent.calculAndSendScore()");
                    agent.calculAndSendScore();
                    break;
                default:
                    break;
                }
            }
        }
        block();
    }
}
